package conson.tech.manage.coupons.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import conson.tech.core.exception.BaseException;
import conson.tech.core.response.Response;
import conson.tech.manage.api.coupons.dto.CouponAppliedDetailDTO;
import conson.tech.manage.api.coupons.dto.CouponUsingRangeDTO;
import conson.tech.manage.api.coupons.dto.UserCouponDetailDTO;
import conson.tech.manage.common.constant.BusinessMessage;
import conson.tech.manage.coupons.constant.CouponsConstants;
import conson.tech.manage.coupons.entity.pojo.CouponsBatch;
import conson.tech.manage.coupons.entity.pojo.CouponsUsers;
import conson.tech.manage.coupons.entity.pojo.CouponsUsersLog;
import conson.tech.manage.coupons.entity.pojo.CouponsUsingRange;
import conson.tech.manage.coupons.mapper.CouponsBatchMapper;
import conson.tech.manage.coupons.mapper.CouponsUsersLogMapper;
import conson.tech.manage.coupons.mapper.CouponsUsersMapper;
import conson.tech.manage.coupons.mapper.CouponsUsingRangeMapper;
import conson.tech.manage.coupons.service.CouponProviderService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 优惠券对外服务实现类
 * Created by guoxt on 2020/7/27.
 */
@Slf4j
@Service
public class CouponProviderServiceImpl implements CouponProviderService {

    @Autowired
    private CouponsUsersMapper couponsUsersMapper;

    @Autowired
    private CouponsBatchMapper couponsBatchMapper;

    @Autowired
    private CouponsUsersLogMapper couponsUsersLogMapper;

    @Autowired
    private StringRedisTemplate redisTemplate;

    @Autowired
    private CouponsUsingRangeMapper couponsUsingRangeMapper;

    @Override
    @Transactional
    public Response lockCoupon(List<String> couponCodeList) {


        log.info("用户优惠券锁定(批量)开始");
        //          校验用户是否存在，暂不需要做了，直接使用userId

        //         校验优惠券发放表中用户是否拥有这些优惠券
        //         校验优惠券发放表中用户拥有该优惠券的状态是否为有效
        for (String couponsCode : couponCodeList) {
            CouponsUsers couponsUser
                    = this.couponsUsersMapper.selectOne(new QueryWrapper<CouponsUsers>().eq("coupons_code", couponsCode).eq("state", 0));
            if (couponsUser == null) {
                throw new BaseException(BusinessMessage.COUPON_VALID_NOT_EXIST_ERROR);
            }
            //锁定时间是否在优惠券的有效期内
            CouponsBatch couponsBatch = this.couponsBatchMapper.selectById(couponsUser.getBatchId());
            if (LocalDateTime.now().isBefore(couponsUser.getStartTime()) || LocalDateTime.now().isAfter(couponsUser.getEndTime())) {
                throw new BaseException(BusinessMessage.COUPON_LOCK_TIME_ERROR);
            }
//            修改用户优惠券的状态
            couponsUser.setState(4);

            this.couponsUsersMapper.updateById(couponsUser);

            // 添加优惠券发放日志表
            //                插入优惠券发放日志表
            CouponsUsersLog couponsUsersLog = new CouponsUsersLog();
            couponsUsersLog.setCreateTime(LocalDateTime.now());
            couponsUsersLog.setCouponsId(couponsUser.getId());
            couponsUsersLog.setCouponsCode(couponsUser.getCouponsCode());
            couponsUsersLog.setCreateName(CouponsConstants.CURRENTUSERNAME);
            couponsUsersLog.setCouponsState(4);
            couponsUsersLog.setOperateDesc("用户优惠券锁定");
            this.couponsUsersLogMapper.insert(couponsUsersLog);
        }

        log.info("用户优惠券锁定(批量)完成");
        return Response.success(true);
    }

    /**
     * 用户优惠券解锁
     *
     * @param couponCodeList
     * @return conson.tech.core.response.Response
     */
    @Override
    @Transactional
    public Response unlockCoupon(List<String> couponCodeList) {

        log.info("用户优惠券解锁(批量)开始");

        //          校验用户是否存在，暂不需要做了，直接使用userId

        for (String couponsCode : couponCodeList) {
            //         校验优惠券发放表中用户是否拥有该优惠券
            //         校验优惠券发放表中用户拥有该优惠券的状态是否为已锁定
            CouponsUsers couponsUser
                    = this.couponsUsersMapper.selectOne(new QueryWrapper<CouponsUsers>().eq("coupons_code", couponsCode).eq("state", 4));
            if (couponsUser == null) {
                throw new BaseException(BusinessMessage.COUPON_VALID_NOT_EXIST_ERROR);
            }
            if (LocalDateTime.now().isBefore(couponsUser.getStartTime()) || LocalDateTime.now().isAfter(couponsUser.getEndTime())) {
                throw new BaseException(BusinessMessage.COUPON_LOCK_TIME_ERROR);
            }
            // 修改优惠券的状态为已使用
            couponsUser.setState(0);
            this.couponsUsersMapper.updateById(couponsUser);


            // 添加优惠券发放日志表
            CouponsUsersLog couponsUsersLog = new CouponsUsersLog();
            couponsUsersLog.setCreateTime(LocalDateTime.now());
            couponsUsersLog.setCouponsId(couponsUser.getId());
            couponsUsersLog.setCouponsCode(couponsUser.getCouponsCode());
            couponsUsersLog.setOperateDesc("用户优惠券解锁");
            couponsUsersLog.setCouponsState(0);
            couponsUsersLog.setCreateName(CouponsConstants.CURRENTUSERNAME);
            this.couponsUsersLogMapper.insert(couponsUsersLog);
        }
        log.info("用户优惠券解锁(批量)完成");
        return Response.success(true);
    }

    @Override
    @Transactional
    public Response appliedCoupon(List<CouponAppliedDetailDTO> couponCodeList) {

        log.info("用户优惠券核销(批量)开始");

        // 校验用户是否存在，暂不需要做了，直接使用userId
        // 修改优惠券的状态为已使用
        // 添加优惠券发放日志表
        for (CouponAppliedDetailDTO couponsCode : couponCodeList) {
            //         校验优惠券发放表中用户是否拥有该优惠券
            //         校验优惠券发放表中用户拥有该优惠券的状态是否为已锁定
            CouponsUsers couponsUser
                    = this.couponsUsersMapper.selectOne(
                    new QueryWrapper<CouponsUsers>().or(wrapper -> wrapper.eq("coupons_code", couponsCode.getCouponCode()).eq("state", 4))
                            .or(wrapper -> wrapper.eq("coupons_code", couponsCode.getCouponCode()).eq("state", 0)));
            if (couponsUser == null) {
                throw new BaseException(BusinessMessage.COUPON_VALID_NOT_EXIST_ERROR);
            }
            //核销时间是否在优惠券的有效期内
            CouponsBatch couponsBatch = this.couponsBatchMapper.selectById(couponsUser.getBatchId());
            if (LocalDateTime.now().isBefore(couponsUser.getStartTime()) || LocalDateTime.now().isAfter(couponsUser.getEndTime())) {
                throw new BaseException(BusinessMessage.COUPON_LOCK_TIME_ERROR);
            }
            CouponsUsingRange usingRange = this.couponsUsingRangeMapper.selectOne(new QueryWrapper<CouponsUsingRange>().eq("batch_id", couponsBatch.getId()));
            if (!usingRange.getUsingId().equals(couponsCode.getUsingId())) {
                throw new BaseException(BusinessMessage.USING_NOT_MATCH_ERROR);
            }
            // 修改优惠券的状态为已使用
            couponsUser.setState(1);
            couponsUser.setUsingId(couponsCode.getUsingId());
//            增加核销时间
            couponsUser.setApplyTime(LocalDateTime.now());
            this.couponsUsersMapper.updateById(couponsUser);

            // 添加优惠券发放日志表
            CouponsUsersLog couponsUsersLog = new CouponsUsersLog();
            couponsUsersLog.setCreateTime(LocalDateTime.now());
            couponsUsersLog.setCouponsId(couponsUser.getId());
            couponsUsersLog.setCouponsCode(couponsUser.getCouponsCode());
            couponsUsersLog.setOperateDesc("用户优惠券核销");
            couponsUsersLog.setCouponsState(1);

            couponsUsersLog.setCreateName(CouponsConstants.CURRENTUSERNAME);
            this.couponsUsersLogMapper.insert(couponsUsersLog);
        }
        log.info("用户优惠券核销(批量)完成");
        return Response.success(true);
    }

    @Override
    public Response returnCoupon(String couponCode) {
        log.info("优惠券原路返还(单张)开始");

        //          校验用户是否存在，暂不需要做了，直接使用userId

        //         校验优惠券发放表中用户是否拥有该优惠券
        //         校验优惠券发放表中用户拥有该优惠券的状态是否为已使用
        CouponsUsers couponsUser
                = this.couponsUsersMapper.selectOne(new QueryWrapper<CouponsUsers>().eq("coupons_code", couponCode).eq("state", 1));
        if (couponsUser == null) {
            throw new BaseException(BusinessMessage.COUPON_VALID_NOT_EXIST_ERROR);
        }


        // 修改优惠券的状态为有效
        //退还后时间是否在优惠券的有效期内，如果在，则置为有效，否则为已作废
        if (LocalDateTime.now().isAfter(couponsUser.getStartTime()) && LocalDateTime.now().isBefore(couponsUser.getEndTime())) {
            couponsUser.setState(0);
            couponsUser.setRefundCount(couponsUser.getRefundCount() + 1);
            couponsUser.setRefundTime(LocalDateTime.now());
            couponsUser.setRefundFlag(1);
            this.couponsUsersMapper.updateById(couponsUser);

            // 添加优惠券发放日志表
            CouponsUsersLog couponsUsersLog = new CouponsUsersLog();
            couponsUsersLog.setCreateTime(LocalDateTime.now());
            couponsUsersLog.setCouponsId(couponsUser.getId());
            couponsUsersLog.setCouponsCode(couponsUser.getCouponsCode());
            couponsUsersLog.setOperateDesc("用户优惠券原路返还");
            couponsUsersLog.setCouponsState(0);
            couponsUsersLog.setCreateName(CouponsConstants.CURRENTUSERNAME);
            this.couponsUsersLogMapper.insert(couponsUsersLog);

            return Response.success(true);
        }
        //退还后时间是否在优惠券的有效期内，如果在，则置为有效，否则为已作废
        couponsUser.setState(2);
        couponsUser.setRefundCount(couponsUser.getRefundCount() + 1);
        couponsUser.setRefundTime(LocalDateTime.now());
        couponsUser.setRefundFlag(1);
        this.couponsUsersMapper.updateById(couponsUser);

        // 添加优惠券发放日志表
        CouponsUsersLog couponsUsersLog = new CouponsUsersLog();
        couponsUsersLog.setCreateTime(LocalDateTime.now());
        couponsUsersLog.setCouponsId(couponsUser.getId());
        couponsUsersLog.setCouponsCode(couponsUser.getCouponsCode());
        couponsUsersLog.setOperateDesc("用户优惠券原路返还");
        couponsUsersLog.setCouponsState(2);
        couponsUsersLog.setCreateName(CouponsConstants.CURRENTUSERNAME);
        this.couponsUsersLogMapper.insert(couponsUsersLog);

        log.info("优惠券原路返还(单张)完成");
        return Response.success(true);
    }

    @Override
    public Response couponConfigDetails(Long userId, List<String> couponCodeList) {

        log.info("获取用户优惠券配置信息列表开始");

        List<UserCouponDetailDTO> collect1 = couponCodeList.stream().map(code -> {
            UserCouponDetailDTO userCouponDetailDTO = new UserCouponDetailDTO();
            CouponsUsers couponsUsers = this.couponsUsersMapper.selectOne(new QueryWrapper<CouponsUsers>().eq("user_id", userId).eq("coupons_code", code));
            userCouponDetailDTO.setState(couponsUsers.getState());


            CouponsBatch couponsBatch = this.couponsBatchMapper.selectById(couponsUsers.getBatchId());
            userCouponDetailDTO.setCouponsCode(code);
            userCouponDetailDTO.setBatchType(couponsBatch.getBatchType());
            userCouponDetailDTO.setBatchName(couponsBatch.getBatchName());
            userCouponDetailDTO.setUsedDes(couponsBatch.getUsedDes());
            userCouponDetailDTO.setBatchTypeName(couponsBatch.getBatchTypeName());
            userCouponDetailDTO.setProvider(couponsBatch.getProvider());
            userCouponDetailDTO.setRangeType(couponsBatch.getRangeType());
            userCouponDetailDTO.setBatchMoney(couponsBatch.getBatchMoney());
            userCouponDetailDTO.setLimitMoney(couponsBatch.getLimitMoney());
            userCouponDetailDTO.setBatchId(couponsBatch.getId());
            userCouponDetailDTO.setStartTime(couponsBatch.getStartTime());
            userCouponDetailDTO.setEndTime(couponsBatch.getEndTime());

            List<CouponsUsingRange> couponsUsingRanges = this.couponsUsingRangeMapper.selectList(new QueryWrapper<CouponsUsingRange>().eq("batch_id", couponsBatch.getId()));

            List<CouponUsingRangeDTO> collect = couponsUsingRanges.stream().map(couponsUsingRange -> {
                CouponUsingRangeDTO couponUsingRangeDTO = new CouponUsingRangeDTO();
                couponUsingRangeDTO.setBatchId(couponsUsingRange.getBatchId().toString());
                couponUsingRangeDTO.setRemark(couponsUsingRange.getRemark());
                couponUsingRangeDTO.setUsingId(String.valueOf(couponsUsingRange.getUsingId()));
                return couponUsingRangeDTO;
            }).collect(Collectors.toList());
            userCouponDetailDTO.setCouponUsingRangeList(collect);

            return userCouponDetailDTO;
        }).collect(Collectors.toList());

        log.info("获取用户优惠券配置信息列表完成");
        return Response.success(collect1);

    }
}
